package com.qlogic.commons.platform.impls.lucene.handler;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.util.LittleEndian;

public class POIPowerPointHandler extends MSOfficeHandler {

	/** The buffer that is written with the content of the PPT. */
	private StringBuffer buffer;

	/**
	 * Hide the public constructor.
	 * <p>
	 */
	public POIPowerPointHandler() {
		buffer = new StringBuffer(4096);
	}

	/**
	 * @see org.jlibrary.core.search.extraction.Extractor#extractText(java.io.File)
	 */
	public String getText(InputStream is, String encoding) throws ContentHandlerException {
		try {
			String text = extractText(is);
			is.close();
			return text;
		} catch (Exception e) {
			throw new ContentHandlerException(e);
		}
	}

	/**
	 * @see org.jlibrary.core.search.extraction.Extractor#extractHeader(java.io.File)
	 */
	public HeaderMetaData extractHeader(File f) throws ContentHandlerException {

		try {
			POIFSReader reader = new POIFSReader();
			reader.registerListener(this);
			FileInputStream fis = new FileInputStream(f);
			reader.read(fis);
			fis.close();
			// extract all information
			return extractMetaInformation();
		} catch (Throwable t) {
			throw new ContentHandlerException(t);
		}

	}

	private String extractText(InputStream in) throws Exception {

		POIFSReader reader = new POIFSReader();
		reader.registerListener(this);
		reader.read(in);

		String result = removeControlChars(buffer.toString());

		// return the final result
		return result;
	}

	/**
	 * @see org.apache.poi.poifs.eventfilesystem.POIFSReaderListener#processPOIFSReaderEvent(org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent)
	 */
	public void processPOIFSReaderEvent(POIFSReaderEvent event) {

		try {

			// super implementation handles document summary
			processPOIFSReaderEvent(event);

			// make sue this is a PPT document
			if (!event.getName().startsWith(POWERPOINT_EVENT_NAME)) {
				return;
			}

			DocumentInputStream input = event.getStream();
			byte[] array = new byte[input.available()];
			input.read(array, 0, input.available());

			for (int i = 0; i < array.length - 20; i++) {
				int type = LittleEndian.getUShort(array, i + 2);
				int size = (int) LittleEndian.getUInt(array, i + 4) + 3;

				String encoding = null;
				switch (type) {
				case PPT_TEXTBYTE_ATOM:
					// this pice is single-byte encoded, let's assume Cp1252
					// since this is most likley
					// anyone who knows how to find out the "right" encoding -
					// please email me
					encoding = ENCODING_CP1252;
				case PPT_TEXTCHAR_ATOM:
					if (encoding == null) {
						// this piece is double-byte encoded, use UTF-16
						encoding = ENCODING_UTF16;
					}
					int start = i + 4 + 1;
					int end = start + size;

					byte[] buf = new byte[size];
					System.arraycopy(buffer, start, buf, 0, buf.length);

					buffer.append(new String(buf, encoding));
					i = end;
				default:
				// noop
				}
			}
		} catch (Exception e) {
			// ignore
		}
	}

	public Document getDocument(InputStream is, String encoding) throws ContentHandlerException {
		String bodyText = getText(is, encoding);
		if (bodyText != null) {
			Document doc = new Document();
			doc.add(new Field(BODY, bodyText, Field.Store.NO,
					Field.Index.TOKENIZED));
			return doc;
		}
		return null;
	}

}
